package org.beetl.sql.test;

import lombok.Data;
import org.beetl.sql.annotation.entity.Auto;
import org.beetl.sql.annotation.entity.AutoID;
import org.beetl.sql.annotation.entity.Column;
import org.beetl.sql.annotation.entity.Table;
import org.beetl.sql.clazz.ClassAnnotation;
import org.beetl.sql.core.SQLManager;
import org.beetl.sql.core.UnderlinedNameConversion;
import org.beetl.sql.core.page.DefaultPageRequest;
import org.beetl.sql.core.page.PageResult;
import org.beetl.sql.mapper.BaseMapper;
import org.beetl.sql.mapper.MapperInvoke;
import org.beetl.sql.mapper.annotation.AutoMapper;
import org.beetl.sql.sample.SampleHelper;
import org.beetl.sql.test.annotation.*;

import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.List;

/**
 *  自定义注解演示
 * @author xiandafu
 * @see Jackson , json注解
 * @see LoadOne, 加载更多数据
 * @see Matcher, mapper扩展新注解
 * @see SchemaTenant, 多租户注解
 *
 */
public class PluginAnnotationSample {
    SQLManager sqlManager;

    public PluginAnnotationSample(SQLManager sqlManager) {
        this.sqlManager = sqlManager;

    }

    public static void main(String[] args) throws Exception {
        SQLManager sqlManager = SampleHelper.getSqlManager();
        PluginAnnotationSample plugin = new PluginAnnotationSample(sqlManager);
//		plugin.testMatcherAnnotation();
//        plugin.testJacksonAnnotation();
//        plugin.loadMore();
        plugin.tenantSchema();




    }

    /**
     * 自定义个Json注解 @Jackson，用于序列化到数据库，或者反序列化
     */
    public void testJacksonAnnotation(){
        UserInfo userInfo = new UserInfo();
        Name name = new Name();
        name.setFirstName("joel");
        name.setLastName("li");
        userInfo.setName(name);
        sqlManager.insert(userInfo);
        Integer id = userInfo.getId();
        userInfo = sqlManager.unique(UserInfo.class,id);
        System.out.println(userInfo.getName());
    }

    /**
     * 自定义一个mapper的扩展注解@Matcher，使得mapper参数中有一个Condition类，能构造查询条件。
     * 也演示了如何自定义BaseMapper和重新实现内置方法
     */
    public void testMatcherAnnotation(){
        MyMapper mapper = sqlManager.getMapper(MyMapper.class);
        {
            //@matcher注解
            List<UserDetail> list = mapper.query(new Condition().append("name", Condition.Opt.equals)
                    ,"lijz");
            System.out.println(list.size());
        }

        {
            // 重新实现的deleteById方法
            try{
                mapper.deleteById(1);
            }catch(Exception ex){
                System.out.println(ex.getMessage());
            }
        }


    }

    /**
     * 查询数据后，在根据注解 @LoadOne定义加载更多数据
     */
    public void loadMore(){
        UserDetail userInfo = sqlManager.unique(UserDetail.class,1);
        System.out.println(userInfo.getDepartmentId());
        System.out.println(userInfo.getDept().getName());

    }
    /**
     * 一个租户一个库。
     */
    public void tenantSchema(){


        sqlManager.setNc(new UnderlinedNameConversion(){
            @Override
            protected String getAnnotationTableName(Class clazz) {
                ClassAnnotation classAnnotation = ClassAnnotation.getClassAnnotation(clazz);
                String name =  classAnnotation.getTableName();
                if(name.indexOf("${schema}")!=-1){
                    String schema =  SchemaTenantContext.tenantSchemaLocals.get();
                    name = name.replace("${schema}",schema);
                }

                return name ;
            }
        });



        //设置当前操作的租户,由于采用h2内存数据库，只有一个schema是public。
        SchemaTenantContext.tenantSchemaLocals.set("public");

        SchemaTenantUser user = sqlManager.unique(SchemaTenantUser.class,1);

        String sql = "select * from ${schema}.sys_user ";
        List<SchemaTenantUser> list = sqlManager.execute(sql,SchemaTenantUser.class,new HashMap());
        System.out.println(list.get(0));

        String pageSql = "select #{page('*')} from ${schema}.sys_user ";
        PageResult<SchemaTenantUser> pageResult = sqlManager.executePageQuery(pageSql,SchemaTenantUser.class,new HashMap<>(),
                DefaultPageRequest.of(1, 10));

    }









    @Table(name="sys_user")
    @Data
    public static class UserInfo{
        @Column("id")
        @AutoID
        Integer id;

        @Column("name")
        @Jackson
        Name name ;
    }
    @Data
    public static class Name{
        String firstName;
        String lastName;
    }


    @Table(name="sys_user")
    @Data
    @LoadOne(name="foo")
    public static class UserDetail{
        @Column("id")
        @AutoID
        Integer id;
        String name;
        Integer departmentId;
        DepartmentInfo dept;
    }

    @Data
    @Table(name="department")
    public static class DepartmentInfo{
        @Column("id")
        @AutoID
        Integer id;
        String name;
    }

    /**
     * 通过schema来设置映射到某个库的某个表
     */
    @Data
    @Table(name="${schema}.sys_user")
    @SchemaTenant
    public static class SchemaTenantUser{
        @Auto
        private Integer id;
        @Column("name")
        private String name;
    }




    public  interface MyMapper extends  MyBaseMapper<UserInfo>{
        /**
         * Matcher是扩展注解，表示执行的sql，需要考虑Condition和后面的参数
         * @param condition
         * @param name
         * @return
         */
        @Matcher
        List<UserDetail> query(Condition condition,String  name);
    }

    /**
     * 构造一个自定的Mapper方法，继承所有BaseMapper,但deleteById会做一些特殊逻辑
     * @param <T>
     */
    public static interface  MyBaseMapper<T> extends BaseMapper{
        @Override
        @AutoMapper(DeleteCheckByIdAMI.class)
        int deleteById(Object key);
    }

    public static class DeleteCheckByIdAMI extends MapperInvoke {

        @Override
        public Object call(SQLManager sm, Class entityClass, Method m, Object[] args) {
            Long id = ((Number)args[0]).longValue();
        	if(id<100){
                throw new IllegalArgumentException("不允许删除 "+id);
            }
            return sm.deleteById(entityClass, args[0]);
        }

    }


}
